﻿Public Class CTokenParcerCharCll
    Inherits CTokenParcerStdBase

    Private mcllChrLegalArr As Char()

    Protected Sub ChrLegalCllSet(cll_i As NSCllG.ICollection(Of Char))
        Dim cllArr As Char() = Nothing

        If cll_i Is Nothing Then
            Array.Resize(cllArr, 0)
        Else
            Array.Resize(cllArr, cll_i.Count)
            cll_i.CopyTo(cllArr, 0)
            Array.Sort(cllArr)
        End If

        mcllChrLegalArr = cllArr
    End Sub

    Sub New(objSeed As CTokenParcerCharCll)
        MyBase.New(objSeed)
        With objSeed
            Array.Resize(mcllChrLegalArr, .mcllChrLegalArr.Length)
            Array.Copy(.mcllChrLegalArr, mcllChrLegalArr, .mcllChrLegalArr.Length)
        End With
    End Sub

    Sub New(numRank_i As Int32)
        MyBase.New(numRank_i)
        ChrLegalCllSet({Char.ConvertFromUtf32(&H20).Chars(0)})
    End Sub

    Sub New(numRank_i As Int32, enmType_i As ETokenParcerStdType)
        MyBase.New(numRank_i, enmType_i)
        ChrLegalCllSet({Char.ConvertFromUtf32(&H20).Chars(0)})
    End Sub

    Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory)
        MyBase.New(numRank_i, objTokenFactory_i)
        ChrLegalCllSet({Char.ConvertFromUtf32(&H20).Chars(0)})
    End Sub


    Sub New(numRank_i As Int32, cllChrLegal_i As NSCllG.ICollection(Of Char))
        MyBase.New(numRank_i)
        ChrLegalCllSet(cllChrLegal_i)
    End Sub

    Sub New(numRank_i As Int32, enmType_i As ETokenParcerStdType, cllChrLegal_i As NSCllG.ICollection(Of Char))
        MyBase.New(numRank_i, enmType_i)
        ChrLegalCllSet(cllChrLegal_i)
    End Sub

    Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory, cllChrLegal_i As NSCllG.ICollection(Of Char))
        MyBase.New(numRank_i, objTokenFactory_i)
        ChrLegalCllSet(cllChrLegal_i)
    End Sub

    Public Property ChrLegalCll As NSCllG.ICollection(Of Char)
        Get
            Return Array.AsReadOnly(mcllChrLegalArr)
        End Get
        Set(cll_i As NSCllG.ICollection(Of Char))
            ChrLegalCllSet(cll_i)
        End Set
    End Property

    Protected Overrides Sub Impl_BegParce(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef numRank_o As Integer)
        If Array.BinarySearch(mcllChrLegalArr, strTextRaw_i.Chars(numPosCurr_io)) >= 0 Then
            numRank_o = mnumRank
        End If
    End Sub

    Protected Overrides Sub Impl_EndParce(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef objToken_o As CTokenBase)
        TokenCreateSafe(strTextRaw_i, numPosCurr_io, 1, Nothing, objToken_o)
        numPosCurr_io += 1
    End Sub

End Class

Public Class CTokenParcerRegexp
    Inherits CTokenParcerStdBase

    Protected mobjREMain As NSRegExp.Regex
    Protected menmPrefixSuffixBehavior As EPrefixSuffixBehavior
    Protected mnumTokenLenMax As Int32
    Protected mobjREMFounded As NSRegExp.Match
    Protected mblnAllowSeekFwd As Boolean

    Public Overridable Property RegExprMain As NSRegExp.Regex
        Get
            Return mobjREMain
        End Get
        Set(obj_i As NSRegExp.Regex)
            mobjREMain = RegExprClone(obj_i)
            menmPrefixSuffixBehavior = EPrefixSuffixBehavior.None
        End Set
    End Property

    Public Overridable Property TokenLenMax As Int32
        Get
            Return mnumTokenLenMax
        End Get
        Set(num_i As Int32)
            If num_i < 0 Then
                Throw New ArgumentOutOfRangeException("TokenLenMax")
            End If

            mnumTokenLenMax = num_i
        End Set
    End Property

    Public Overridable Property PrefixSuffixBehavior As EPrefixSuffixBehavior
        Get
            Return menmPrefixSuffixBehavior
        End Get
        Set(enm_i As EPrefixSuffixBehavior)
            If enm_i <> EPrefixSuffixBehavior.None AndAlso mobjREMain.GetGroupNumbers().Length = 0 Then
                Throw New ArgumentException("RegExprMain have invalid pattern. No capture group.", "objRegExMain_i")
            End If

            menmPrefixSuffixBehavior = enm_i
        End Set
    End Property

    Public Overridable Property AllowSeekFwd As Boolean
        Get
            Return mblnAllowSeekFwd
        End Get
        Set(bln_i As Boolean)
            mblnAllowSeekFwd = bln_i
        End Set
    End Property

    Protected Function RegExprClone(ByVal objREPattern_i As NSRegExp.Regex) As NSRegExp.Regex
        Return New NSRegExp.Regex(objREPattern_i.ToString(), (objREPattern_i.Options Or NSRegExp.RegexOptions.Compiled))
    End Function

    Private Sub InitMe(ByVal objRegExMain_i As NSRegExp.Regex, ByVal numTokenLenMax_i As Int32, ByVal enmPrefixSuffixBehavior_i As EPrefixSuffixBehavior)
        If numTokenLenMax_i < 0 Then
            Throw New ArgumentOutOfRangeException("numTokenLenMax_i")
        End If

        If enmPrefixSuffixBehavior_i <> EPrefixSuffixBehavior.None AndAlso objRegExMain_i.GetGroupNumbers().Length = 0 Then
            Throw New ArgumentException("RegExprMain have invalid pattern. No capture group.", "objRegExMain_i")
        End If

        mobjREMain = RegExprClone(objRegExMain_i)
        menmPrefixSuffixBehavior = enmPrefixSuffixBehavior_i
        mnumTokenLenMax = numTokenLenMax_i
    End Sub


    Sub New(objSeed As CTokenParcerRegexp)
        MyBase.New(objSeed)
        With objSeed
            mblnAllowSeekFwd = .mblnAllowSeekFwd
            menmPrefixSuffixBehavior = .menmPrefixSuffixBehavior
            mnumTokenLenMax = .mnumTokenLenMax
            mobjREMain = .mobjREMain
            mobjREMFounded = Nothing
        End With
    End Sub


    Public Sub New(numRank_i As Int32, ByVal objRegExMain_i As NSRegExp.Regex, ByVal numTokenLenMax_i As Int32)
        MyBase.New(numRank_i)
        InitMe(objRegExMain_i, numTokenLenMax_i, EPrefixSuffixBehavior.None)
    End Sub

    Public Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory, ByVal objRegExMain_i As NSRegExp.Regex, ByVal numTokenLenMax_i As Int32)
        MyBase.New(numRank_i, objTokenFactory_i)
        InitMe(objRegExMain_i, numTokenLenMax_i, EPrefixSuffixBehavior.None)
    End Sub

    Public Sub New(numRank_i As Int32, enmType_i As ETokenParcerStdType, ByVal objRegExMain_i As NSRegExp.Regex, ByVal numTokenLenMax_i As Int32)
        MyBase.New(numRank_i, enmType_i)
        InitMe(objRegExMain_i, numTokenLenMax_i, EPrefixSuffixBehavior.None)
    End Sub


    Public Sub New(numRank_i As Int32, ByVal objRegExMain_i As NSRegExp.Regex)
        MyBase.New(numRank_i)
        InitMe(objRegExMain_i, 0, EPrefixSuffixBehavior.None)
    End Sub

    Public Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory, ByVal objRegExMain_i As NSRegExp.Regex)
        MyBase.New(numRank_i, objTokenFactory_i)
        InitMe(objRegExMain_i, 0, EPrefixSuffixBehavior.None)
    End Sub

    Public Sub New(numRank_i As Int32, enmType_i As ETokenParcerStdType, ByVal objRegExMain_i As NSRegExp.Regex)
        MyBase.New(numRank_i, enmType_i)
        InitMe(objRegExMain_i, 0, EPrefixSuffixBehavior.None)
    End Sub


    Public Sub New(numRank_i As Int32, ByVal objRegExMain_i As NSRegExp.Regex, ByVal numTokenLenMax_i As Int32, ByVal enmPrefixSuffixBehavior_i As EPrefixSuffixBehavior)
        MyBase.New(numRank_i)
        InitMe(objRegExMain_i, numTokenLenMax_i, enmPrefixSuffixBehavior_i)
    End Sub

    Public Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory, ByVal objRegExMain_i As NSRegExp.Regex, ByVal numTokenLenMax_i As Int32, ByVal enmPrefixSuffixBehavior_i As EPrefixSuffixBehavior)
        MyBase.New(numRank_i, objTokenFactory_i)
        InitMe(objRegExMain_i, numTokenLenMax_i, enmPrefixSuffixBehavior_i)
    End Sub

    Public Sub New(numRank_i As Int32, enmType_i As ETokenParcerStdType, ByVal objRegExMain_i As NSRegExp.Regex, ByVal numTokenLenMax_i As Int32, ByVal enmPrefixSuffixBehavior_i As EPrefixSuffixBehavior)
        MyBase.New(numRank_i, enmType_i)
        InitMe(objRegExMain_i, numTokenLenMax_i, enmPrefixSuffixBehavior_i)
    End Sub


    Protected Overrides Sub Impl_BegParce(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef numRank_o As Integer)
        Dim strTextRaw As String

        If mblnAllowSeekFwd OrElse mnumTokenLenMax = 0 Then
            strTextRaw = strTextRaw_i.Substring(numPosCurr_io)
        Else
            strTextRaw = strTextRaw_i.Substring(numPosCurr_io, mnumTokenLenMax)
        End If

        Dim objREM = mobjREMain.Match(strTextRaw)

        If objREM.Success AndAlso (mblnAllowSeekFwd OrElse objREM.Index = 0) Then
            mobjREMFounded = objREM
            numRank_o = mnumRank
        End If
    End Sub

    Protected Sub EndParceCore(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef numPosBeg_o As Int32, ByRef numLength_o As Int32)
        Dim objREMC As NSRegExp.Capture

        numLength_o = mobjREMFounded.Length
        numPosCurr_io += mobjREMFounded.Index

        If menmPrefixSuffixBehavior = EPrefixSuffixBehavior.None Then
            numPosBeg_o = numPosCurr_io
            numPosCurr_io += numLength_o
        Else
            Dim numGLastIdx = mobjREMFounded.Groups.Count - 1

            If numGLastIdx < 0 Then
                Throw New XWackyParcerTreeInvalid("CTokenParcerRegexp::RegExprMain have invalid pattern. No capture group.")
            End If

            objREMC = mobjREMFounded.Groups(numGLastIdx)

            Dim numPrefixLen = objREMC.Index - mobjREMFounded.Index
            Dim numSuffixLen = (mobjREMFounded.Index + mobjREMFounded.Length) - (objREMC.Index + objREMC.Length)

            If (menmPrefixSuffixBehavior And EPrefixSuffixBehavior.PrefixExcludeFromToken) = EPrefixSuffixBehavior.PrefixExcludeFromToken Then
                numLength_o -= numPrefixLen
                numPosBeg_o = numPosCurr_io + numPrefixLen
            Else
                numPosBeg_o = numPosCurr_io + mobjREMFounded.Index
            End If

            If (menmPrefixSuffixBehavior And EPrefixSuffixBehavior.SuffixExcludeFromToken) = EPrefixSuffixBehavior.SuffixExcludeFromToken Then
                numLength_o -= numSuffixLen
            End If

            numPosCurr_io += mobjREMFounded.Length

            If (menmPrefixSuffixBehavior And EPrefixSuffixBehavior.DontMovePosAboveSuffix) = EPrefixSuffixBehavior.DontMovePosAboveSuffix Then
                numPosCurr_io -= numSuffixLen
            End If
        End If

        mobjREMFounded = Nothing
    End Sub


    Protected Overrides Sub Impl_EndParce(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef objToken_o As CTokenBase)
        Dim numPosBeg As Int32
        Dim numLength As Int32

        EndParceCore(strTextRaw_i, numPosCurr_io, numPosBeg, numLength)
        TokenCreateSafe(strTextRaw_i, numPosBeg, CUInt(numLength), Nothing, objToken_o)
    End Sub

End Class

Public Class CTokenParcerRegexpWTransform
    Inherits CTokenParcerRegexp

    Private mcllTransformArr() As CSearchReplaceBase

    Protected Sub TransformationCllSet(ByVal cllTransformation_i As NSCllG.IEnumerable(Of CSearchReplaceBase))
        mcllTransformArr = CSearchReplaceBase.TransformationCllToArr(cllTransformation_i)
    End Sub

    Sub New(objSeed As CTokenParcerRegexpWTransform)
        MyBase.New(objSeed)
        With objSeed
            Dim numLen = .mcllTransformArr.Length

            Array.Resize(mcllTransformArr, numLen)
            Array.Copy(.mcllTransformArr, mcllTransformArr, numLen)
        End With
    End Sub

    Public Sub New(numRank_i As Int32, ByVal objRegExMain_i As NSRegExp.Regex, ByVal numTokenLenMax_i As Int32, ByVal cllTransformation_i As NSCllG.IEnumerable(Of CSearchReplaceBase))
        MyClass.New(numRank_i, objRegExMain_i, numTokenLenMax_i, EPrefixSuffixBehavior.None, cllTransformation_i)
    End Sub

    Public Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory, ByVal objRegExMain_i As NSRegExp.Regex, ByVal numTokenLenMax_i As Int32, ByVal cllTransformation_i As NSCllG.IEnumerable(Of CSearchReplaceBase))
        MyClass.New(numRank_i, objTokenFactory_i, objRegExMain_i, numTokenLenMax_i, EPrefixSuffixBehavior.None, cllTransformation_i)
    End Sub

    Public Sub New(numRank_i As Int32, enmType_i As ETokenParcerStdType, ByVal objRegExMain_i As NSRegExp.Regex, ByVal numTokenLenMax_i As Int32, ByVal cllTransformation_i As NSCllG.IEnumerable(Of CSearchReplaceBase))
        MyClass.New(numRank_i, enmType_i, objRegExMain_i, numTokenLenMax_i, EPrefixSuffixBehavior.None, cllTransformation_i)
    End Sub


    Public Sub New(numRank_i As Int32, ByVal objRegExMain_i As NSRegExp.Regex, ByVal cllTransformation_i As NSCllG.IEnumerable(Of CSearchReplaceBase))
        MyClass.New(numRank_i, objRegExMain_i, 0, EPrefixSuffixBehavior.None, cllTransformation_i)
    End Sub

    Public Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory, ByVal objRegExMain_i As NSRegExp.Regex, ByVal cllTransformation_i As NSCllG.IEnumerable(Of CSearchReplaceBase))
        MyClass.New(numRank_i, objTokenFactory_i, objRegExMain_i, 0, EPrefixSuffixBehavior.None, cllTransformation_i)
    End Sub

    Public Sub New(numRank_i As Int32, enmType_i As ETokenParcerStdType, ByVal objRegExMain_i As NSRegExp.Regex, ByVal cllTransformation_i As NSCllG.IEnumerable(Of CSearchReplaceBase))
        MyClass.New(numRank_i, enmType_i, objRegExMain_i, 0, EPrefixSuffixBehavior.None, cllTransformation_i)
    End Sub


    Public Sub New(numRank_i As Int32, ByVal objRegExMain_i As NSRegExp.Regex, ByVal numTokenLenMax_i As Int32, ByVal enmPrefixSuffixBehavior_i As EPrefixSuffixBehavior, ByVal cllTransformation_i As NSCllG.IEnumerable(Of CSearchReplaceBase))
        MyBase.New(numRank_i, objRegExMain_i, numTokenLenMax_i, enmPrefixSuffixBehavior_i)
        TransformationCllSet(cllTransformation_i)
    End Sub

    Public Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory, ByVal objRegExMain_i As NSRegExp.Regex, ByVal numTokenLenMax_i As Int32, ByVal enmPrefixSuffixBehavior_i As EPrefixSuffixBehavior, ByVal cllTransformation_i As NSCllG.IEnumerable(Of CSearchReplaceBase))
        MyBase.New(numRank_i, objTokenFactory_i, objRegExMain_i, numTokenLenMax_i, enmPrefixSuffixBehavior_i)
        TransformationCllSet(cllTransformation_i)
    End Sub

    Public Sub New(numRank_i As Int32, enmType_i As ETokenParcerStdType, ByVal objRegExMain_i As NSRegExp.Regex, ByVal numTokenLenMax_i As Int32, ByVal enmPrefixSuffixBehavior_i As EPrefixSuffixBehavior, ByVal cllTransformation_i As NSCllG.IEnumerable(Of CSearchReplaceBase))
        MyBase.New(numRank_i, enmType_i, objRegExMain_i, numTokenLenMax_i, enmPrefixSuffixBehavior_i)
        TransformationCllSet(cllTransformation_i)
    End Sub


    Public Property TransformationCll As NSCllG.ICollection(Of CSearchReplaceBase)
        Get
            Return Array.AsReadOnly(mcllTransformArr)
        End Get
        Set(cll_i As NSCllG.ICollection(Of CSearchReplaceBase))
            TransformationCllSet(cll_i)
        End Set
    End Property

    Protected Overrides Sub Impl_EndParce(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef objToken_o As CTokenBase)
        Dim numPosBeg As Int32
        Dim numLength As Int32

        EndParceCore(strTextRaw_i, numPosCurr_io, numPosBeg, numLength)

        If CanCreateToken() Then
            Dim strToken = strTextRaw_i.Substring(numPosBeg, numLength)

            For Each mobjSRIt As CSearchReplaceBase In mcllTransformArr
                strToken = mobjSRIt.Execute(strToken)
            Next

            TokenCreate(strTextRaw_i, numPosBeg, CUInt(numLength), strToken, objToken_o)
        End If
    End Sub
End Class

Public Class CTokenParcerPhrase
    Inherits CTokenParcerStdBase

    Protected mstrPhrase As String
    Protected mnumPrefixLen As Int32
    Protected mnumSuffixLen As Int32
    Protected menmComparisonType As StringComparison
    Protected menmPrefixSuffixBehavior As EPrefixSuffixBehavior
    Protected mblnAllowSeekFwd As Boolean

    Public Overridable Property AllowSeekFwd As Boolean
        Get
            Return mblnAllowSeekFwd
        End Get
        Set(bln_i As Boolean)
            mblnAllowSeekFwd = bln_i
        End Set
    End Property

    Public Property Phrase As String
        Get
            Return mstrPhrase
        End Get
        Set(str_i As String)
            If String.IsNullOrEmpty(str_i) Then
                Throw New ArgumentException("Parameter can not be empty string or null.", "PhraseMain")
            End If

            mnumPrefixLen = 0
            mnumSuffixLen = 0

            mstrPhrase = str_i
        End Set
    End Property

    Public Property SuffixLen As Int32
        Get
            Return mnumSuffixLen
        End Get
        Set(num_i As Int32)
            If menmPrefixSuffixBehavior = EPrefixSuffixBehavior.None Then
                Throw New InvalidOperationException("The parser does not specify behavior for prefix or suffix.")
            End If

            If num_i < 0 OrElse num_i > mstrPhrase.Length - mnumPrefixLen Then
                Throw New ArgumentOutOfRangeException("SuffixLen")
            End If

            mnumSuffixLen = num_i
        End Set
    End Property

    Public Property PrefixLen As Int32
        Get
            Return mnumPrefixLen
        End Get
        Set(num_i As Int32)
            If menmPrefixSuffixBehavior = EPrefixSuffixBehavior.None Then
                Throw New InvalidOperationException("The parser does not specify behavior for prefix or suffix.")
            End If

            If num_i < 0 OrElse num_i > mstrPhrase.Length - mnumSuffixLen Then
                Throw New ArgumentOutOfRangeException("PrefixLen")
            End If

            mnumPrefixLen = num_i
        End Set
    End Property

    Public Sub PrefixSuffixLenSet(ByVal numPrefixLen_i As Int32, ByVal numSuffixLen_i As Int32)
        If menmPrefixSuffixBehavior = EPrefixSuffixBehavior.None Then
            Throw New InvalidOperationException("The parser does not specify behavior for prefix or suffix.")
        End If

        PrefixSuffixLenSetLocal(mstrPhrase, menmPrefixSuffixBehavior, numPrefixLen_i, numSuffixLen_i)
    End Sub

    Public ReadOnly Property PhraseSuffix As String
        Get
            Return mstrPhrase.Substring(mstrPhrase.Length - mnumSuffixLen)
        End Get
    End Property

    Public ReadOnly Property PhrasePrefix As String
        Get
            Return mstrPhrase.Substring(0, mnumPrefixLen)
        End Get
    End Property

    Public Overridable Property PrefixSuffixBehavior As EPrefixSuffixBehavior
        Get
            Return menmPrefixSuffixBehavior
        End Get
        Set(enm_i As EPrefixSuffixBehavior)
            If enm_i = EPrefixSuffixBehavior.None Then
                mnumPrefixLen = 0
                mnumSuffixLen = 0
            End If

            menmPrefixSuffixBehavior = enm_i
        End Set
    End Property

    Public Overridable Property ComparisonType As StringComparison
        Get
            Return menmComparisonType
        End Get
        Set(enm_i As StringComparison)
            menmComparisonType = enm_i
        End Set
    End Property

    Protected Overridable Sub PrefixSuffixLenSetLocal(ByVal strPhrase_i As String, ByVal enmPrefixSuffixBehavior_i As EPrefixSuffixBehavior, ByVal numPrefixLen_i As Int32, ByVal numSuffixLen_i As Int32)
        If numPrefixLen_i < 0 Then
            Throw New ArgumentOutOfRangeException("numPrefixLen_i")
        End If

        If numSuffixLen_i < 0 Then
            Throw New ArgumentOutOfRangeException("numSuffixLen_i")
        End If

        If numPrefixLen_i + numSuffixLen_i >= strPhrase_i.Length Then
            Throw New ArgumentOutOfRangeException("numPrefixLen_i, numSuffixLen_i", "Prefix and Suffix length > PhraseMain length.")
        End If

        If (numPrefixLen_i <> 0 Or numSuffixLen_i <> 0) AndAlso enmPrefixSuffixBehavior_i = EPrefixSuffixBehavior.None Then
            Throw New InvalidOperationException("The parser does not specify behavior for prefix or suffix.")
        End If

        mnumSuffixLen = numSuffixLen_i
        mnumPrefixLen = numPrefixLen_i
    End Sub

    Private Sub InitMe(ByVal strPhrase_i As String, ByVal numPrefixLen_i As Int32, ByVal numSuffixLen_i As Int32, ByVal enmPrefixSuffixBehavior_i As EPrefixSuffixBehavior, ByVal enmComparisonType_i As StringComparison, ByVal blnAllowSeekFwd_i As Boolean)
        If String.IsNullOrEmpty(strPhrase_i) Then
            Throw New ArgumentNullException("strPhrase_i", "Parameter can not be empty string or null.")
        End If

        PrefixSuffixLenSetLocal(strPhrase_i, enmPrefixSuffixBehavior_i, numPrefixLen_i, numSuffixLen_i)
        mstrPhrase = strPhrase_i
        menmComparisonType = enmComparisonType_i
        menmPrefixSuffixBehavior = enmPrefixSuffixBehavior_i
        mblnAllowSeekFwd = blnAllowSeekFwd_i
    End Sub

    Private Sub InitMe(ByVal strPhrase_i As String, ByVal enmComparisonType_i As StringComparison, ByVal blnAllowSeekFwd_i As Boolean)
        If String.IsNullOrEmpty(strPhrase_i) Then
            Throw New ArgumentNullException("strPhrase_i", "Parameter can not be empty string or null.")
        End If

        mnumSuffixLen = 0
        mnumPrefixLen = 0
        mstrPhrase = strPhrase_i
        menmComparisonType = enmComparisonType_i
        menmPrefixSuffixBehavior = EPrefixSuffixBehavior.None
        mblnAllowSeekFwd = blnAllowSeekFwd_i
    End Sub

    Sub New(objSeed As CTokenParcerPhrase)
        MyBase.New(objSeed)
        With objSeed
            mstrPhrase = .mstrPhrase
            mnumPrefixLen = .mnumPrefixLen
            mnumSuffixLen = .mnumSuffixLen
            menmComparisonType = .menmComparisonType
            menmPrefixSuffixBehavior = .menmPrefixSuffixBehavior
            mblnAllowSeekFwd = .mblnAllowSeekFwd
        End With
    End Sub

    Sub New(numRank_i As Int32, ByVal strPhrase_i As String)
        MyBase.New(numRank_i)
        MyClass.InitMe(strPhrase_i, StringComparison.Ordinal, False)
    End Sub

    Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory, ByVal strPhrase_i As String)
        MyBase.New(numRank_i, objTokenFactory_i)
        MyClass.InitMe(strPhrase_i, StringComparison.Ordinal, False)
    End Sub

    Sub New(numRank_i As Int32, enmType_i As ETokenParcerStdType, ByVal strPhrase_i As String)
        MyBase.New(numRank_i, enmType_i)
        MyClass.InitMe(strPhrase_i, StringComparison.Ordinal, False)
    End Sub


    Sub New(numRank_i As Int32, ByVal strPhrase_i As String, ByVal enmComparisonType_i As StringComparison, ByVal blnAllowSeekFwd_i As Boolean)
        MyBase.New(numRank_i)
        MyClass.InitMe(strPhrase_i, enmComparisonType_i, blnAllowSeekFwd_i)
    End Sub

    Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory, ByVal strPhrase_i As String, ByVal enmComparisonType_i As StringComparison, ByVal blnAllowSeekFwd_i As Boolean)
        MyBase.New(numRank_i, objTokenFactory_i)
        MyClass.InitMe(strPhrase_i, enmComparisonType_i, blnAllowSeekFwd_i)
    End Sub

    Sub New(numRank_i As Int32, enmType_i As ETokenParcerStdType, ByVal strPhrase_i As String, ByVal enmComparisonType_i As StringComparison, ByVal blnAllowSeekFwd_i As Boolean)
        MyBase.New(numRank_i, enmType_i)
        MyClass.InitMe(strPhrase_i, enmComparisonType_i, blnAllowSeekFwd_i)
    End Sub


    Sub New(numRank_i As Int32, ByVal strPhrase_i As String, ByVal numPrefixLen_i As Int32, ByVal numSuffixLen_i As Int32, ByVal enmPrefixSuffixBehavior_i As EPrefixSuffixBehavior, ByVal enmComparisonType_i As StringComparison, ByVal blnAllowSeekFwd_i As Boolean)
        MyBase.New(numRank_i)
        MyClass.InitMe(strPhrase_i, numPrefixLen_i, numSuffixLen_i, enmPrefixSuffixBehavior_i, enmComparisonType_i, blnAllowSeekFwd_i)
    End Sub

    Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory, ByVal strPhrase_i As String, ByVal numPrefixLen_i As Int32, ByVal numSuffixLen_i As Int32, ByVal enmPrefixSuffixBehavior_i As EPrefixSuffixBehavior, ByVal enmComparisonType_i As StringComparison, ByVal blnAllowSeekFwd_i As Boolean)
        MyBase.New(numRank_i, objTokenFactory_i)
        MyClass.InitMe(strPhrase_i, numPrefixLen_i, numSuffixLen_i, enmPrefixSuffixBehavior_i, enmComparisonType_i, blnAllowSeekFwd_i)
    End Sub

    Sub New(numRank_i As Int32, enmType_i As ETokenParcerStdType, ByVal strPhrase_i As String, ByVal numPrefixLen_i As Int32, ByVal numSuffixLen_i As Int32, ByVal enmPrefixSuffixBehavior_i As EPrefixSuffixBehavior, ByVal enmComparisonType_i As StringComparison, ByVal blnAllowSeekFwd_i As Boolean)
        MyBase.New(numRank_i, enmType_i)
        MyClass.InitMe(strPhrase_i, numPrefixLen_i, numSuffixLen_i, enmPrefixSuffixBehavior_i, enmComparisonType_i, blnAllowSeekFwd_i)
    End Sub


    Protected Overrides Sub Impl_BegParce(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef numRank_o As Integer)
        If mblnAllowSeekFwd Then
            Dim num As Int32

            If numPosCurr_io < strTextRaw_i.Length Then
                num = strTextRaw_i.IndexOf(mstrPhrase, numPosCurr_io, menmComparisonType)
            Else
                num = -1
            End If

            If num >= numPosCurr_io Then
                numPosCurr_io = num
                numRank_o = mnumRank
            End If
        ElseIf MStringUtil.StringEqualsSafe(strTextRaw_i, numPosCurr_io, mstrPhrase, menmComparisonType) Then
            numRank_o = mnumRank
        End If
    End Sub

    Protected Sub EndParceCore(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef numPosBeg_o As Int32, ByRef numLength_o As Int32)
        numLength_o = mstrPhrase.Length
        numPosBeg_o = numPosCurr_io
        numPosCurr_io += numLength_o

        If menmPrefixSuffixBehavior <> EPrefixSuffixBehavior.None Then
            If (menmPrefixSuffixBehavior And EPrefixSuffixBehavior.SuffixExcludeFromToken) = EPrefixSuffixBehavior.SuffixExcludeFromToken Then
                numPosBeg_o += mnumPrefixLen
                numLength_o -= mnumPrefixLen
            End If

            If (menmPrefixSuffixBehavior And EPrefixSuffixBehavior.PrefixExcludeFromToken) = EPrefixSuffixBehavior.PrefixExcludeFromToken Then
                numLength_o -= mnumSuffixLen
            End If

            If (menmPrefixSuffixBehavior And EPrefixSuffixBehavior.DontMovePosAboveSuffix) = EPrefixSuffixBehavior.DontMovePosAboveSuffix Then
                numPosCurr_io -= mnumSuffixLen
            End If
        End If
    End Sub

    Protected Overrides Sub Impl_EndParce(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef objToken_o As NSTZWackyParcer.CTokenBase)
        Dim numLength As Int32
        Dim numPosBeg As Int32

        EndParceCore(strTextRaw_i, numPosCurr_io, numPosBeg, numLength)
        TokenCreateSafe(strTextRaw_i, numPosBeg, CUInt(numLength), Nothing, objToken_o)
    End Sub

End Class

Public Class CTokenParcerPhraseWTransform
    Inherits CTokenParcerPhrase

    Private mcllTransformArr() As CSearchReplaceBase

    Public Property TransformationCll As NSCllG.ICollection(Of CSearchReplaceBase)
        Get
            Return Array.AsReadOnly(mcllTransformArr)
        End Get
        Set(cll_i As NSCllG.ICollection(Of CSearchReplaceBase))
            TransformationCllSet(cll_i)
        End Set
    End Property

    Protected Sub TransformationCllSet(ByVal cllTransformation_i As NSCllG.IEnumerable(Of CSearchReplaceBase))
        mcllTransformArr = CSearchReplaceBase.TransformationCllToArr(cllTransformation_i)
    End Sub

    Protected Overrides Sub Impl_EndParce(strTextRaw_i As String, ByRef numPosCurr_io As Integer, ByRef objToken_o As NSTZWackyParcer.CTokenBase)
        Dim numLength As Int32
        Dim numPosBeg As Int32

        EndParceCore(strTextRaw_i, numPosCurr_io, numPosBeg, numLength)

        If CanCreateToken() Then
            Dim strPhrase = strTextRaw_i.Substring(numPosBeg, numLength)

            For Each mobjSRIt As CSearchReplaceBase In mcllTransformArr
                strPhrase = mobjSRIt.Execute(strPhrase)
            Next

            TokenCreate(strTextRaw_i, numPosBeg, CUInt(numLength), strPhrase, objToken_o)
        End If
    End Sub

    Sub New(objSeed As CTokenParcerPhraseWTransform)
        MyBase.New(objSeed)
        With objSeed
            Dim numLen = .mcllTransformArr.Length
            Array.Resize(mcllTransformArr, numLen)
            Array.Copy(.mcllTransformArr, mcllTransformArr, numLen)
        End With
    End Sub

    Sub New(numRank_i As Int32, ByVal strPhrase_i As String)
        MyBase.New(numRank_i, strPhrase_i)
        mcllTransformArr = {}
    End Sub

    Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory, ByVal strPhrase_i As String)
        MyBase.New(numRank_i, objTokenFactory_i, strPhrase_i)
        mcllTransformArr = {}
    End Sub

    Sub New(numRank_i As Int32, enmType_i As ETokenParcerStdType, ByVal strPhrase_i As String)
        MyBase.New(numRank_i, enmType_i, strPhrase_i)
        mcllTransformArr = {}
    End Sub


    Sub New(numRank_i As Int32, ByVal strPhrase_i As String, ByVal enmComparisonType_i As StringComparison, ByVal blnAllowSeekFwd_i As Boolean)
        MyBase.New(numRank_i, strPhrase_i, enmComparisonType_i, blnAllowSeekFwd_i)
        mcllTransformArr = {}
    End Sub

    Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory, ByVal strPhrase_i As String, ByVal enmComparisonType_i As StringComparison, ByVal blnAllowSeekFwd_i As Boolean)
        MyBase.New(numRank_i, objTokenFactory_i, strPhrase_i, enmComparisonType_i, blnAllowSeekFwd_i)
        mcllTransformArr = {}
    End Sub

    Sub New(numRank_i As Int32, enmType_i As ETokenParcerStdType, ByVal strPhrase_i As String, ByVal enmComparisonType_i As StringComparison, ByVal blnAllowSeekFwd_i As Boolean)
        MyBase.New(numRank_i, enmType_i, strPhrase_i, enmComparisonType_i, blnAllowSeekFwd_i)
        mcllTransformArr = {}
    End Sub


    Sub New(numRank_i As Int32, ByVal strPhrase_i As String, ByVal numPrefixLen_i As Int32, ByVal numSuffixLen_i As Int32, ByVal enmPrefixSuffixBehavior_i As EPrefixSuffixBehavior, ByVal enmComparisonType_i As StringComparison, ByVal blnAllowSeekFwd_i As Boolean, ByVal cllTransformation_i As NSCllG.IEnumerable(Of CSearchReplaceBase))
        MyBase.New(numRank_i, strPhrase_i, numPrefixLen_i, numSuffixLen_i, enmPrefixSuffixBehavior_i, enmComparisonType_i, blnAllowSeekFwd_i)
        TransformationCllSet(cllTransformation_i)
    End Sub

    Sub New(numRank_i As Int32, objTokenFactory_i As ITokenFactory, ByVal strPhrase_i As String, ByVal numPrefixLen_i As Int32, ByVal numSuffixLen_i As Int32, ByVal enmPrefixSuffixBehavior_i As EPrefixSuffixBehavior, ByVal enmComparisonType_i As StringComparison, ByVal blnAllowSeekFwd_i As Boolean, ByVal cllTransformation_i As NSCllG.IEnumerable(Of CSearchReplaceBase))
        MyBase.New(numRank_i, objTokenFactory_i, strPhrase_i, numPrefixLen_i, numSuffixLen_i, enmPrefixSuffixBehavior_i, enmComparisonType_i, blnAllowSeekFwd_i)
        TransformationCllSet(cllTransformation_i)
    End Sub

    Sub New(numRank_i As Int32, enmType_i As ETokenParcerStdType, ByVal strPhrase_i As String, ByVal numPrefixLen_i As Int32, ByVal numSuffixLen_i As Int32, ByVal enmPrefixSuffixBehavior_i As EPrefixSuffixBehavior, ByVal enmComparisonType_i As StringComparison, ByVal blnAllowSeekFwd_i As Boolean, ByVal cllTransformation_i As NSCllG.IEnumerable(Of CSearchReplaceBase))
        MyBase.New(numRank_i, enmType_i, strPhrase_i, numPrefixLen_i, numSuffixLen_i, enmPrefixSuffixBehavior_i, enmComparisonType_i, blnAllowSeekFwd_i)
        TransformationCllSet(cllTransformation_i)
    End Sub
End Class


Public NotInheritable Class CSearchReplaceWholeSting
    Inherits CSearchReplaceBase

    Dim menmComparisonType As StringComparison
    Dim mnumRank As Int32
    Dim mstrReplaceTo As String
    Dim mstrSearch As String

    Public Overrides ReadOnly Property Rank As Integer
        Get
            Return mnumRank
        End Get
    End Property

    Public ReadOnly Property ReplaceTo As String
        Get
            Return mstrReplaceTo
        End Get
    End Property


    Public ReadOnly Property Search As String
        Get
            Return mstrSearch
        End Get
    End Property


    Public Sub New(ByVal numRank_i As Int32, ByVal strSearch_i As String, ByVal strReplace_i As String)
        MyClass.New(numRank_i, strSearch_i, strReplace_i, StringComparison.Ordinal)
    End Sub

    Public Sub New(ByVal numRank_i As Int32, ByVal strSearch_i As String, ByVal strReplace_i As String, ByVal enmComparisonType_i As StringComparison)
        If String.IsNullOrEmpty(strSearch_i) Then
            Throw New ArgumentNullException("strSearch_i")
        End If

        If strSearch_i = strReplace_i Then
            Throw New ArgumentException("strReplace_i can not be equal strSearch_i.", "strReplace_i")
        End If

        mstrSearch = strSearch_i

        If strReplace_i Is Nothing Then
            mstrReplaceTo = String.Empty
        Else
            mstrReplaceTo = strReplace_i
        End If

        menmComparisonType = enmComparisonType_i
        mnumRank = numRank_i
    End Sub

    Public Overrides Function Execute(strSrc_i As String) As String
        If strSrc_i.Equals(strSrc_i, menmComparisonType) Then
            Return mstrReplaceTo
        Else
            Return strSrc_i
        End If
    End Function
End Class
